package com.xmim.core.session.user;


import com.xmim.core.entity.UserDetail;
import com.xmim.core.session.SessionFactory;
import com.xmim.core.session.SessionManager;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

@Slf4j
public abstract class AbstractUserSession implements UserSession {

    protected final SessionManager sessionManger;
    protected final SessionFactory fulcrumFactory;
    //通道
    private Object context;
    //用户
    private UserDetail user;
    //session唯一标示
    private String sessionId;
    // session中存储的session 变量属性值
    private Map<String, Object> attributes = new HashMap<String, Object>();

    public AbstractUserSession(SessionFactory fulcrumFactory, String sessionId) {
        this.sessionId = sessionId;
        this.fulcrumFactory = fulcrumFactory;
        this.sessionManger = fulcrumFactory.getSessionManager();
    }

    @Override
    public AbstractUserSession setUser(UserDetail user) {
        user.setSessionId(sessionId);
        this.user = user;
        return this;
    }

    //和channel 通道实现双向绑定
    @Override
    public AbstractUserSession bind(Object context) {
        log.debug("LocalSession 绑定会话 " + context);
        this.context = context;
        this.checkContext(context);
        this.onBind();
        this.sessionManger.addSession(this.sessionId, this);
        return this;
    }

    protected abstract void onBind();

    @Override
    public AbstractUserSession unbind() {
        log.debug("LocalSession 解除会话 " + context);
        this.sessionManger.destroySession(getSessionId());
        this.close();
        return this;
    }

    @Override
    public String getSessionId() {
        return sessionId;
    }


    @Override
    public synchronized AbstractUserSession addAttribute(String key, Object value) {
        attributes.put(key, value);
        return this;
    }

    @Override
    public synchronized <T2> T2 getAttribute(String key) {
        return (T2) attributes.get(key);
    }

    @Override
    public Object getContext() {
        checkContext(context);
        return context;
    }

    protected abstract void checkContext(Object context);

    @Override
    public UserDetail getUser() {
        return user;
    }

    @Override
    public boolean isLogin() {
        if (user == null) {
            return false;
        }
        return user.isLogin();
    }


}
